<template>
  <div class="tree-wrapper">
    <!-- 搜索框 -->
    <div class="head-container">
      <!-- 添加标题 -->
      <div class="title">{{ typeInfo.typeName }}</div>
    </div>

    <!-- 树形控件 -->
    <div class="tree-container">
      <el-tree
        ref="treeRef"
        :check-strictly="true"
        :data="deptList"
        :expand-on-click-node="false"
        :filter-node-method="filterNode"
        :props="defaultProps"
        :show-checkbox="showCheckbox"
        default-expand-all
        highlight-current
        node-key="id"
        @check="handleCheck"
        @node-click="handleNodeClick"
      >
        <template #default="{ data }">
          <div class="tree-node-content">
            <span>{{ data.name }}</span>
            <el-popover
              :visible="data.showMenu"
              popper-class="custom-popover"
              trigger="click"
              @hide="handlePopoverHide(data)"
              @show="handlePopoverShow(data)"
            >
              <template #reference>
                <el-icon class="more-icon" @click.stop="handleMoreClick(data)">
                  <More />
                </el-icon>
              </template>
              <el-menu class="custom-menu">
                <el-menu-item @click="handleAction('addChild', data)">
                  <div class="menu-item-content">添加节点</div>
                </el-menu-item>
                <el-menu-item @click="handleAction('edit', data)">
                  <div class="menu-item-content">修改</div>
                </el-menu-item>
                <el-menu-item @click="handleAction('delete', data)">
                  <div class="menu-item-content">删除</div>
                </el-menu-item>
              </el-menu>
            </el-popover>
          </div>
        </template>
      </el-tree>
    </div>

    <!-- 添加新增目录弹框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogType === 'add' ? `新增${typeInfo.typeName}` : `修改${typeInfo.typeName}`"
      width="20%"
    >
      <el-form :model="formData">
        <el-form-item :label="`名称`">
          <el-input v-model="formData.name" :placeholder="`请输入${typeInfo.typeName}`" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { ElMessageBox, ElTree } from 'element-plus'
import { ProjectApi } from '@/api/dk/project'
import { defaultProps, handleTree } from '@/utils/tree'
import { More } from '@element-plus/icons-vue'

defineOptions({ name: 'MaterialTree' })
const props = defineProps({
  typeInfo: {
    type: Object,
    required: true
  },
  showCheckbox: {
    type: Boolean,
    default: false
  }
})

const deptName = ref('')
const deptList = ref<Tree[]>([])
const treeRef = ref<InstanceType<typeof ElTree>>()
const lastClickedNode = ref<Tree | null>(null)
const dialogVisible = ref(false)
const dialogType = ref<'add' | 'edit'>('add')
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const formData = ref<{
  id?: number | string
  name: string
  parentId?: string | number | null
}>({
  name: '',
  parentId: null
})

// 获取部门树数据
const getTree = async () => {
  const type = props.typeInfo.type
  const res = await ProjectApi.getMaterialClassList(type)
  deptList.value = handleTree(res).map((item) => ({ ...item, showMenu: false }))
}

// 过滤节点
const filterNode = (name: string, data: Tree) => !name || data.name.includes(name)

// 添加 emit 定义
const emit = defineEmits(['node-click', 'refresh-list', 'refresh-material-class', 'check'])

// 节点点击处理
const handleNodeClick = (data: Tree) => {
  console.log('树节点点击:', data)
  // 设置当前选中节点
  treeRef.value?.setCurrentKey(data.id)
  // 触发点击事件
  emit('node-click', data.id)
}

// 监听搜索关键字
watch(deptName, (val) => treeRef.value?.filter(val))

// 菜单显示/隐藏处理
const handlePopoverShow = (data: Tree) => {
  document.addEventListener('click', (e) => handleClickOutside(e, data))
}

const handlePopoverHide = (data: Tree) => {
  document.removeEventListener('click', (e) => handleClickOutside(e, data))
}

const handleMoreClick = (data: Tree) => {
  if (lastClickedNode.value && lastClickedNode.value !== data) {
    lastClickedNode.value.showMenu = false
  }
  data.showMenu = !data.showMenu
  lastClickedNode.value = data
}

const handleAction = (actionType: string, data: Tree) => {
  // 提取需要的节点数据
  const nodeData = {
    id: data.id,
    name: data.name,
    parentId: data.parentId
  }
  console.log('当前点击的节点数据:', JSON.stringify(nodeData))

  data.showMenu = false
  if (actionType === 'addChild') {
    dialogType.value = 'add'
    dialogVisible.value = true
    formData.value = {
      name: '',
      parentId: nodeData.id
    }
  } else if (actionType === 'edit') {
    dialogType.value = 'edit'
    dialogVisible.value = true
    formData.value = {
      name: nodeData.name,
      id: nodeData.id
    }
  } else if (actionType === 'delete') {
    // 检查是否为根节点
    if (!data.parentId) {
      message.warning('根节点不能删除')
      return
    }

    // 检查是否有子节点
    if (data.children && data.children.length > 0) {
      message.warning('请先删除子节点')
      return
    }

    // 删除确认
    ElMessageBox.confirm(`确定要删除${props.typeInfo.typeName} ${nodeData.name} 吗？`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(async () => {
        // 调用删除接口
        // await MaterialApi.deleteChild([Number(nodeData.id)])
        message.success(t('common.delSuccess'))
        // 删除成功后刷新树
        await getTree()
      })
      .catch(() => {})
  }
}

const handleClickOutside = (event: MouseEvent, data: Tree) => {
  const target = event.target as HTMLElement
  if (!target.closest('.el-popover') && !target.closest('.el-menu')) {
    data.showMenu = false
    document.removeEventListener('click', (e) => handleClickOutside(e, data))
  }
}

// 修改 handleSubmit 函数
const handleSubmit = async () => {
  const data = {
    ...(formData.value as ProjectApi.CourseMaterialClassDO), // 保留原有字段
    type: props.typeInfo.type
  }
  console.log('提交的数据:', JSON.stringify(data))
  // 调用后端 API，获取返回的新节点数据
  // const res = await MaterialApi.addAndUpdateChild(data)

  message.success(t('common.createSuccess'))

  // 关闭弹框
  dialogVisible.value = false
  // 清空表单数据
  formData.value = {
    name: '',
    parentId: null
  }

  // 刷新树形数据
  await getTree()

  // 触发刷新目录列表事件
  emit('refresh-material-class')

  // 等待 DOM 更新
  await nextTick()

  // 如果是新增操作，选中并触发新节点的点击事件
  if (dialogType.value === 'add' && res.id) {
    // 设置当前选中节点
    treeRef.value?.setCurrentKey(res.id)
    // 触发节点点击事件
    emit('node-click', res.id)
  }
}

// 添加一个方法来获取指定节点的所有子节点ID
const getChildrenIds = (nodeId: number): number[] => {
  const ids: number[] = [nodeId] // 包含当前节点ID

  // 递归查找子节点
  const findChildren = (node: Tree) => {
    if (node.children && node.children.length > 0) {
      node.children.forEach((child) => {
        ids.push(Number(child.id))
        // 继续递归查找子节点的子节点
        findChildren(child)
      })
    }
  }

  // 在树中找到目标节点
  const findTargetNode = (nodes: Tree[]): Tree | null => {
    for (const node of nodes) {
      if (Number(node.id) === nodeId) {
        return node
      }
      if (node.children && node.children.length > 0) {
        const found = findTargetNode(node.children)
        if (found) return found
      }
    }
    return null
  }

  // 找到目标节点并获取其所有子节点ID
  const targetNode = findTargetNode(deptList.value)
  if (targetNode) {
    findChildren(targetNode)
  }

  console.log('找到的所有ID:', ids)
  return ids
}

// 修改 handleCheck 函数
const handleCheck = async (data: Tree, { checkedKeys }) => {
  // 获取当前节点的所有子节点ID
  const childrenIds = getChildrenIds(Number(data.id))

  // 获取当前所有选中的节点
  const currentCheckedKeys = treeRef.value?.getCheckedKeys() || []

  // 判断是勾选还是取消勾选
  const isChecked = checkedKeys.includes(data.id)

  // 检查当前节点是否有子节点
  if (data.children && data.children.length > 0) {
    try {
      await ElMessageBox.confirm(`是否${isChecked ? '选择' : '取消'}所有子节点？`, '提示', {
        confirmButtonText: '是',
        cancelButtonText: '否',
        type: 'warning'
      })

      // 用户点击"是"，处理所有子节点
      if (isChecked) {
        // 合并当前选中的节点和新选中的子节点
        const newCheckedKeys = [...new Set([...currentCheckedKeys, ...childrenIds])]
        treeRef.value?.setCheckedKeys(newCheckedKeys)
      } else {
        // 从当前选中节点中移除要取消的节点
        const remainingKeys = currentCheckedKeys.filter((key) => !childrenIds.includes(Number(key)))
        treeRef.value?.setCheckedKeys(remainingKeys)
      }
    } catch {
      // 用户点击"否"，只处理当前节点
      if (isChecked) {
        // 保持其他选中节点，只添加当前节点
        const newCheckedKeys = [...new Set([...currentCheckedKeys, data.id])]
        treeRef.value?.setCheckedKeys(newCheckedKeys)
      } else {
        // 保持其他选中节点，只移除当前节点
        const remainingKeys = currentCheckedKeys.filter((key) => key !== data.id)
        treeRef.value?.setCheckedKeys(remainingKeys)
      }
    }
  }

  // 获取最新的选中状态
  const finalCheckedKeys = treeRef.value?.getCheckedKeys() || []
  const finalCheckedNodes = treeRef.value?.getCheckedNodes() || []
  const finalHalfCheckedKeys = treeRef.value?.getHalfCheckedKeys() || []
  const finalHalfCheckedNodes = treeRef.value?.getHalfCheckedNodes() || []

  // 触发父组件的 check 事件
  emit('check', {
    checkedData: data,
    checkedKeys: finalCheckedKeys,
    checkedNodes: finalCheckedNodes,
    halfCheckedKeys: finalHalfCheckedKeys,
    halfCheckedNodes: finalHalfCheckedNodes
  })
}

// 添加获取选中节点的方法
const getCheckedNodes = () => {
  return treeRef.value?.getCheckedNodes()
}

// 添加获取选中节点 key 的方法
const getCheckedKeys = () => {
  return treeRef.value?.getCheckedKeys()
}

// 暴露方法给父组件使用
defineExpose({
  getChildrenIds,
  getCheckedNodes,
  getCheckedKeys
})

onMounted(() => getTree())
onUnmounted(() => document.removeEventListener('click', (e) => handleClickOutside(e, null as any)))

interface Tree {
  id: number | string
  name: string
  parentId?: number | string
  children?: Tree[]
  showMenu?: boolean
}
</script>
<style>
.el-popper.custom-popover {
  padding: 4px !important;
  width: auto !important;
  min-width: 0 !important;
}

.custom-menu {
  border: none !important;
}

.custom-menu .el-menu-item {
  height: 32px !important;
  line-height: 32px !important;
  padding: 0 8px !important;
  min-width: 0 !important;
  width: auto !important;
}

.custom-menu .menu-item-content {
  font-size: 14px;
  width: 60px;
  text-align: left;
  white-space: nowrap;
}

.el-menu--popup {
  padding: 0 !important;
  min-width: 0 !important;
}
</style>

<style scoped>
.tree-node-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 8px;
}

.tree-node-content .more-icon {
  opacity: 0;
  color: #999;
  font-size: 14px;
  margin-right: 4px;
}

/* 树的整体样式 */
:deep(.el-tree) {
  background: transparent;
  font-size: 13px;

  /* 树节点样式 */
  .el-tree-node__content {
    height: 28px;
    padding: 0;

    &:hover {
      background-color: #f5f7fa;
    }
  }

  /* 展开图标样式 */
  .el-tree-node__expand-icon {
    font-size: 12px;
    padding: 0 6px;

    &.expanded {
      transform: rotate(90deg);
    }
  }

  /* 树节点缩进 */
  .el-tree-node__children {
    padding-left: 18px;
  }

  /* 当前选中节点样式 */
  .is-current > .el-tree-node__content {
    background-color: #f0f7ff;
    color: var(--el-color-primary);
    font-weight: 500;
  }
}

/* 标题样式 */
.head-container {
  padding: 8px;
  border-bottom: 1px solid #f0f0f0;

  .title {
    font-size: 13px;
    color: #606266;
    height: 32px;
    line-height: 32px;
    padding: 0;
    margin: 0;
  }
}

/* 弹出菜单样式 */
.custom-menu {
  .el-menu-item {
    height: 28px !important;
    line-height: 28px !important;

    &:hover {
      background-color: #f5f7fa;
    }
  }

  .menu-item-content {
    font-size: 13px;
  }
}

/* 树的容器样式 */
.tree-wrapper {
  background-color: #fff;
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
  border-radius: 2px;
}

.tree-container {
  height: 850px;
}

.head-container {
  padding: 8px;
  border-bottom: 1px solid #f0f0f0;

  .title {
    font-size: 13px;
    color: #606266;
    height: 32px;
    line-height: 32px;
    padding: 0;
    margin: 0;
  }
}
</style>
